# -*- coding: utf-8 -*-
"""
@Time ： 2021/12/12 20:10
@Auth ： Mr. William 1052949192
@Company ：特斯汀学院 @testingedu.com.cn
@Function ：特斯汀学院接口自动化关键字库
"""
import json
import time
import traceback

import jsonpath
import requests

from common import Logger
from common.decs import relations


class Inter:
    def __init__(self):
        # 用一个实例变量来做会话管理
        self.session = requests.session()
        self.result = ''
        self.jsonres = {}
        self.url = ''

        self.relations = {'time': str(int(time.time()))}

    def seturl(self, url):
        """
        设置url前缀
        :param url: 前缀地址
        """
        self.url = url
        return True, self.url

    @relations
    def get(self, api='', params=''):
        """
        实现http的post发包
        :param api: 接口url地址
        :param params: 接口的参数
        """
        if api.startswith('http'):
            # 如果接口名字是绝对url地址
            pass
        else:
            # 如果接口名字是部分名字，就拼上前缀
            if self.url.endswith('/'):
                api = self.url + api
            else:
                api = self.url + '/' + api

        api += '?' + params
        Logger.debug(api)

        # 协议层面发包是否成功
        try:
            result = self.session.get(api)
            self.result = result.text
            Logger.debug(self.result)
            try:
                self.jsonres = json.loads(self.result)
                return True, self.jsonres
            except Exception as e:
                Logger.warning(traceback.format_exc())
                self.jsonres = {'error': e.__str__()}
                return True, self.result

        except Exception as e:
            Logger.exception(e)
            self.result = e.__str__()
            return False, self.result

    @relations
    def post(self, api='', params=''):
        """
        实现http的post发包
        :param api: 接口url地址
        :param params: 接口的参数
        """
        if api.startswith('http'):
            # 如果接口名字是绝对url地址
            pass
        else:
            # 如果接口名字是部分名字，就拼上前缀
            if self.url.endswith('/'):
                api = self.url + api
            else:
                api = self.url + '/' + api

        # 处理url格式参数为键值对
        if params.__contains__('='):
            params = self.__param_to_data(params)

        # 处理json传参
        if type(params) == str and params.startswith('{'):
            json_params = json.loads(params)
            params = None
        else:
            json_params = None

        # 协议层面发包是否成功
        try:
            result = self.session.post(api, data=params, json=json_params)
            self.result = result.text
            Logger.debug(self.result)
            try:
                self.jsonres = json.loads(self.result)
                return True, self.jsonres
            except Exception as e:
                Logger.warning(traceback.format_exc())
                self.jsonres = {'error': e.__str__()}
                return True, self.result

        except Exception as e:
            Logger.exception(e)
            self.result = e.__str__()
            return False, self.result

    @relations
    def addheader(self, key='', value=''):
        """
        往session里面添加头的键值对
        :param key: 头的键名
        :param value: 键的值
        """
        self.session.headers[key] = value
        Logger.debug(self.session.headers)
        return True, self.session.headers

    def removeheader(self, key=''):
        """
        往session里面添加头的键值对
        :param key: 头的键名
        :param value: 键的值
        """
        try:
            self.session.headers.pop(key)
        except:
            pass
        Logger.debug(self.session.headers)
        return True, self.session.headers

    @relations
    def assertequals(self, jsonkey='', expect_value=''):
        """
        校验上一步请求返回的json结果里面，键的值是否和期望值一样
        :param jsonkey: 返回的json结果里面的键
        :param expect_value: 期望值
        """
        try:
            value = jsonpath.jsonpath(self.jsonres, jsonkey)[0]
        except:
            value = '取值失败'
            Logger.info('FAIL')
            return False, value

        if str(value) == str(expect_value):
            Logger.info('PASS')
            return True, value
        else:
            Logger.info('FAIL')
            return False, value

    @relations
    def assertcontains(self, jsonkey='', expect_value=''):
        """
        校验上一步请求返回的json结果里面，键的值是否和期望值一样
        :param jsonkey: 返回的json结果里面的键
        :param expect_value: 期望值
        """
        try:
            value = jsonpath.jsonpath(self.jsonres, jsonkey)[0]
        except:
            value = '取值失败'
            Logger.info('FAIL')
            return False, value

        if str(value).__contains__(str(expect_value)):
            Logger.info('PASS')
            return True, value
        else:
            Logger.info('FAIL')
            return False, value

    def savejson(self, keys='', param_names=''):
        """
        保存上一步请求的结果里面的键值对到关联字典
        :param keys: 关键字列表
        :param values: 保存后参数的名字
        :return:
        """
        # 处理如果传了保存哪些key
        if keys:
            # 有多个key
            if keys.startswith('['):
                keys = eval(keys)
            else:
                # 兼容只传一个键名
                keys = [keys]

            # 处理有多个参数名的情况
            if param_names.startswith('['):
                param_names = eval(param_names)
            else:
                # 处理只有一个参数名
                if param_names:
                    param_names = [param_names]

            # 添加键值对
            for i in range(len(keys)):
                # 如果传了参数名，就保存为指定的参数名
                if param_names:
                    try:
                        name = param_names[i]
                    except Exception as e:
                        # 如果只传了部分参数名，其他的用默认键名
                        name = keys[i]

                    self.relations[name] = self.jsonres.get(keys[i])
                else:
                    # 如果没传，就保存为默认的键名
                    name = keys[i]
                    self.relations[name] = self.jsonres.get(keys[i])
        else:
            # 什么都没传，默认保存所有
            if self.jsonres and type(self.jsonres) == dict:
                self.relations.update(self.jsonres)

        Logger.debug(self.relations)
        return True, self.relations

    def __param_to_data(self, params=''):
        if params:
            data_dict = {}
            # 先用&把键值对切割
            key_values = params.split('&')
            # 遍历键值对
            for key_value in key_values:
                # 用等号把键和值切割出来
                temp = key_value.split('=')
                key = temp[0]
                try:
                    value = temp[1]
                except:
                    value = ''

                data_dict[key] = value

            return data_dict
        else:
            return {}
